﻿using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using App.Common;
using QxFramework.Core;
using System;
using System.IO;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

public class MapManager : LogicModuleBase,IMapManager
{
    private int roomNumX = 2;
    private int roomNumY = 3;
    private static MapEditorBase.MapEditor _mapEditor;
    private Dictionary<int,string> _mapFile;
    /// <summary>
    /// 加载地图文件
    /// </summary>
    public void InitMapFile()
    {
        _mapFile = new Dictionary<int, string>();
        var list = ResourceManager.Instance.LoadAll<TextAsset>("Text/MapData/");
        for (int i = 0; i < list.Length; i++)
        {
            Regex regex = new Regex(@"mapID\D+\d+");
            var match = regex.Match(list[i].text);
            Regex regex1 = new Regex(@"\d+");
            var match1 = regex1.Match(match.Value);
            int mapID = int.Parse(match1.Value);
            _mapFile.Add(mapID, list[i].text);
        }
        _mapEditor = new MapEditorBase.MapEditor();
        List<Vector2Int> offsetPos = new List<Vector2Int>();
        for (int i = 0; i < roomNumY; i++)
        {
            for (int j = 0; j < roomNumX; j++)
            {
                offsetPos.Insert(UnityEngine.Random.Range(0, offsetPos.Count), new Vector2Int(j, i));
            }
        }
        _mapEditor.roomLen = roomNumX;
        _mapEditor.roomWide = roomNumY;

        for (int i = 0; i < roomNumX * roomNumY; i++)
        {
            var rdm = UnityEngine.Random.Range(2, Data.Instance.TableAgent.CollectKey1("AllRoom").Count);
            //0是初始房间 1是boss房间
            if (i < 2)
                rdm = i;
            var mapRoom = GetRoomMap(Data.Instance.TableAgent.GetInt("AllRoom", rdm.ToString(), "RoomName"));
            mapRoom.mapID = rdm;
            mapRoom.roomID = (offsetPos[i].x * roomNumY) + offsetPos[i].y;
            mapRoom.roomClear = false;
            mapRoom.roomStatue = MapEditorBase.RoomStatue.Unknown;
            _mapEditor.mapRooms.Add(mapRoom.roomID, mapRoom);
        }
    }
    /// <summary>
    /// 初始化地图数据
    /// </summary>
    /// <param name="MapName"></param>
    public void InitMapData(string MapName)
    {
        try
        {
            for (int i = 0; i < roomNumX * roomNumY; i++)
            {
                //相邻地砖的xy偏移量
                int offX = (_mapEditor.mapRooms[i].roomSize.maxX - _mapEditor.mapRooms[i].roomSize.minX) + ((i % roomNumX > 0) ? (int)_mapEditor.mapRooms[i - 1].offsetPos.x : 0);
                int offY = (_mapEditor.mapRooms[i].roomSize.maxY - _mapEditor.mapRooms[i].roomSize.minY) + ((i >= roomNumX) ? (int)_mapEditor.mapRooms[i - roomNumX].offsetPos.y : 0);
                if (i % roomNumX == 0)
                    offX = 0;
                else
                {
                    offX += (_mapEditor.mapRooms[i - 1].roomSize.maxX - _mapEditor.mapRooms[i - 1].roomSize.minX);
                    offX -= (int)((_mapEditor.mapRooms[i].roomSize.maxX - _mapEditor.mapRooms[i].roomSize.minX) / 20) * 10;
                }
                if (i < roomNumX)
                    offY = 20;
                else
                {
                    offY += (_mapEditor.mapRooms[i - roomNumX].roomSize.maxY - _mapEditor.mapRooms[i - roomNumX].roomSize.minY) - 10;
                    offY -= (int)((_mapEditor.mapRooms[i].roomSize.maxY - _mapEditor.mapRooms[i].roomSize.minY) / 20) * 10;
                }
                _mapEditor.mapRooms[i].offsetPos.x = offX;
                _mapEditor.mapRooms[i].offsetPos.y = offY;
                AddOffsetPos(_mapEditor.mapRooms[i].roomID);

                Tuple<int, int> YPos = new Tuple<int, int>(_mapEditor.mapRooms[i].roomSize.minY, _mapEditor.mapRooms[i].roomSize.maxY);
                Tuple<int, int> XPos = new Tuple<int, int>(_mapEditor.mapRooms[i].roomSize.minX, _mapEditor.mapRooms[i].roomSize.maxX);
                AddMapGrounds(YPos, XPos, i);

            }
        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
    }
    /// <summary>
    /// 初始化门和走廊
    /// </summary>
    public void InitDoorsAndCorridors()
    {
        int[] aspect = { 0, roomNumY - 1, 0, roomNumX - 1 };
        int[] link = { -roomNumX, roomNumX, -1, 1 };
        AddDoors(roomNumX, roomNumY, aspect, link);
        AddCorridors(roomNumX, roomNumY);
    }
    /// <summary>
    /// 初始化边缘墙壁
    /// </summary>
    public void InitEdgeWall()
    {
        for (int i = 0; i < roomNumY * roomNumX; i++)
        {
            Tuple<int, int> YPos = new Tuple<int, int>(_mapEditor.mapRooms[i].roomSize.minY, _mapEditor.mapRooms[i].roomSize.maxY);
            Tuple<int, int> XPos = new Tuple<int, int>(_mapEditor.mapRooms[i].roomSize.minX, _mapEditor.mapRooms[i].roomSize.maxX);
            AddEdgeWall(YPos, XPos, i);
            InitWall(i);
        }
        AddEdgeWall();
        InitWall();
    }
    public MapEditorBase.MapEditor GetMapEditor()
    {
        return _mapEditor;
    }
    public MapEditorBase.MapRoom GetCertainRoom(int roomID)
    {
        return _mapEditor.mapRooms[roomID];
    }


    /// <summary>
    /// 添加门
    /// </summary>
    /// <param name="roomNumX"></param>
    /// <param name="roomNumY"></param>
    /// <param name="aspect"></param>
    /// <param name="link"></param>
    private void AddDoors(int roomNumX, int roomNumY, int[] aspect, int[] link)
    {

        for (int i = 0; i < roomNumY; i++)
        {
            for (int j = 0; j < roomNumX; j++)
            {
                //房间ID
                int index = i * roomNumX + j;
                int[] edges = { _mapEditor.mapRooms[index].roomSize.minY, _mapEditor.mapRooms[index].roomSize.maxY, _mapEditor.mapRooms[index].roomSize.minX, _mapEditor.mapRooms[index].roomSize.maxX };

                //下上左右是否可以有通道
                for (int k = 0; k < 4; k++)
                {
                    if (k <= 1 && i == aspect[k])
                        continue;
                    if (k > 1 && j % roomNumX == aspect[k])
                        continue;

                    List<int> list = new List<int>();
                    if (k <= 1)
                        list = _mapEditor.mapRooms[index].mapGrounds[edges[k]];
                    else
                        foreach (var item in _mapEditor.mapRooms[index].mapGrounds)
                            list.Add(item.Key);
                    int rdm = list[0];
                    int key = 0;
                    if (list.Count != 1)
                        rdm = list[UnityEngine.Random.Range(1, list.Count - 1)];
                    if (k <= 1)
                        key = GetHashPosKey(edges[k], rdm);
                    else
                    {
                        key = GetHashPosKey(rdm, edges[k]);
                    }
                    //防止找到空地
                    while(!_mapEditor.mapRooms[index].mapGroundPos.ContainsKey(key))
                    {
                        list.Remove(rdm);
                        rdm = list[UnityEngine.Random.Range(0, list.Count)];
                        if (k <= 1)
                            key = GetHashPosKey(edges[k], rdm);
                        else
                        {
                            key = GetHashPosKey(rdm, edges[k]);
                        }
                    }
                    float doorX = _mapEditor.mapRooms[index].mapGroundPos[key].position.x;
                    float doorY = _mapEditor.mapRooms[index].mapGroundPos[key].position.y;
                    _mapEditor.mapRooms[index].mapDoors.doorPos.Add(new Vector3(doorX, doorY, 1.0f));
                    _mapEditor.mapRooms[index].mapDoors.linkRoomID.Add(index + link[k]);
                    _mapEditor.mapRooms[index].mapDoors.doorDic[GetHashPosKey((int)(doorY * 2), (int)(doorX * 2))] = (MapEditorBase.DoorDirection)k;
                }
            }
        }
    }
    /// <summary>
    /// 添加走廊
    /// </summary>
    /// <param name="index"></param>
    private void AddCorridors(int roomNumX,int roomNumY)
    {
        for (int i = 0; i < roomNumY; i++)
        {
            for (int j = 0; j < roomNumX; j++)
            {
                //房间ID
                int index = i * roomNumX + j;
                var linkRoom = _mapEditor.mapRooms[index].mapDoors.linkRoomID;
                for (int n = 0; n < linkRoom.Count; n++)
                {
                    if (linkRoom[n] < index)
                        continue;
                    var doorPos = _mapEditor.mapRooms[index].mapDoors.doorPos[n];
                    Vector3 linkDoorPos = new Vector3(0, 0, 0);
                    var linkDoor = _mapEditor.mapRooms[linkRoom[n]].mapDoors;
                    for (int k = 0; k < linkDoor.linkRoomID.Count; k++)
                    {
                        if (linkDoor.linkRoomID[k] == index)
                            linkDoorPos = linkDoor.doorPos[k];
                    }
                    MapEditorBase.DoorDirection dic = _mapEditor.mapRooms[index].mapDoors.doorDic[GetHashPosKey((int)(doorPos.y * 2), (int)(doorPos.x * 2))];
                    switch (dic)
                    {
                        case MapEditorBase.DoorDirection.Above:
                        case MapEditorBase.DoorDirection.Below:
                            AddCorridorMono(index, true, doorPos, linkDoorPos, linkRoom[n]);
                            break;
                        default:
                            AddCorridorMono(index, false, doorPos, linkDoorPos, linkRoom[n]);
                            break;
                    }
                }
            }
        }
    }
    private void CheckVec(ref Vector3 front, ref Vector3 behind, bool vertical)
    {
        var temp = new Vector2(0, 0);
        if (vertical && front.y > behind.y)
        {
            temp = behind;
            behind = front;
            front = temp;
        }
        if (!vertical && front.x > behind.x)
        {
            temp = behind;
            behind = front;
            front = temp;
        }
    }
    private void GetDistance(ref float distance,Vector3 start, Vector3 end, bool vertical)
    {
        if (vertical)
            distance = end.y - start.y;
        else
            distance = end.x - start.x;
    }
    /// <summary>
    /// 添加走廊到地图数据
    /// </summary>
    /// <param name="index"></param>
    /// <param name="vertical"></param>
    /// <param name="startPos"></param>
    /// <param name="endPos"></param>
    /// <param name="linkRoom"></param>
    private void AddCorridorMono(int index, bool vertical,Vector3 startPos,Vector3 endPos,int linkRoom)
    {
        MapEditorBase.MapCorridor mapCorridor = new MapEditorBase.MapCorridor();
        mapCorridor.direction = vertical ? MapEditorBase.CorridorDirection.Vertical:MapEditorBase.CorridorDirection.Horizontal;
        mapCorridor.linkRoomID = new Vector2Int(index, linkRoom);
        Vector2 len = new Vector2(0, 0);
        if (vertical)
            len = new Vector2(0, 2.5f);
        else
            len = new Vector2(2.5f, 0);
        mapCorridor.doorKey = new Vector2Int(
            GetHashPosKey((int)((startPos.y + len.y) * 2), (int)((startPos.x + len.x) * 2)), 
            GetHashPosKey((int)((endPos.y - len.y) * 2), (int)((endPos.x - len.x) * 2)));

        float distance = -1;
        var end = endPos;
        var start = startPos;
        CheckVec(ref start, ref end, vertical);
        while (distance != 0)
        {
            start.x += len.x;
            start.y += len.y;
            int key = GetHashPosKey((int)(start.y * 2), (int)(start.x * 2));
            if (!mapCorridor.mapGroundPos.ContainsKey(key))
                AddCorridorGround(mapCorridor, new Vector3(start.x, start.y, 1.0f));

            GetDistance(ref distance, start, end, vertical);

            if (distance == 0)
                break;
            end.x -= len.x;
            end.y -= len.y;
            key = GetHashPosKey((int)(end.y * 2), (int)(end.x * 2));
            if (!mapCorridor.mapGroundPos.ContainsKey(key))
                AddCorridorGround(mapCorridor, new Vector3(end.x, end.y, 1.0f));

            GetDistance(ref distance, start, end, vertical);
        }
        CheckVec(ref start, ref end, !vertical);
        GetDistance(ref distance, start, end, !vertical);
        if (vertical)
            len = new Vector2(2.5f, 0);
        else
            len = new Vector2(0, 2.5f);
 
        while (distance > 2.5)
        {
            start.x += len.x;
            start.y += len.y;
            int key = GetHashPosKey((int)(start.y * 2), (int)(start.x * 2));
            if (!mapCorridor.mapGroundPos.ContainsKey(key))
                AddCorridorGround(mapCorridor, new Vector3(start.x, start.y, 1.0f));

            GetDistance(ref distance, start, end, !vertical);
            if (distance == 0)
                break;
        }
        _mapEditor.mapCorridors.Add(mapCorridor);
        foreach(var item in mapCorridor.mapGroundPos)
        {
            var ground = item.Value;
            AddMonoList(null, ground, "Ground");
        }
    }

    private void AddCorridorGround(MapEditorBase.MapCorridor mapCorridor, Vector3 pos)
    {
        MapEditorBase.MapGround ground = new MapEditorBase.MapGround(pos, SceneType.Floor, MonoAttribute.None, new List<int>());
        int key = GetHashPosKey((int)(ground.position.y * 2), (int)(ground.position.x * 2));
        UpdateMapGrounds((int)(ground.position.x * 2), (int)(ground.position.y * 2), mapCorridor.mapGrounds);
        mapCorridor.mapGroundPos.Add(key, ground);
    }
    /// <summary>
    /// 添加墙壁偏移量
    /// </summary>
    /// <param name="roomID"></param>
    private void AddOffsetPos(int roomID)
    {
        for (int i = 0; i < _mapEditor.mapRooms[roomID].mapWalls.Count; i++)
        {
            _mapEditor.mapRooms[roomID].mapWalls[i].position.x += _mapEditor.mapRooms[roomID].offsetPos.x;
            _mapEditor.mapRooms[roomID].mapWalls[i].position.y += _mapEditor.mapRooms[roomID].offsetPos.y;
            _mapEditor.mapRooms[roomID].mapWalls[i].position.z = 1.0f;
        }

    }
    /// <summary>
    /// 更新偏移后的地面坐标
    /// </summary>
    /// <param name="YPos"></param>偏移前的Y最值
    /// <param name="XPos"></param>偏移前的X最值
    /// <param name="roomID"></param>
    private void AddMapGrounds(Tuple<int, int> YPos, Tuple<int, int> XPos, int roomID)
    {
        Dictionary<int, MapEditorBase.MapGround> mapGroundPos = new Dictionary<int, MapEditorBase.MapGround>();
        Dictionary<int, List<int>> mapGrounds = new Dictionary<int, List<int>>();
        for (int y = YPos.Item1; y <= YPos.Item2; y += 5)
        {
            for (int x = XPos.Item1; x <= XPos.Item2; x += 5)
            {
                int nowGround = GetHashPosKey(y, x);
                if (!_mapEditor.mapRooms[roomID].mapGroundPos.ContainsKey(nowGround))
                    continue;
                //附加偏移量
                var pos = _mapEditor.mapRooms[roomID].mapGroundPos[nowGround].position;
                pos.x += _mapEditor.mapRooms[roomID].offsetPos.x;
                pos.y += _mapEditor.mapRooms[roomID].offsetPos.y;
                int tempKey = GetHashPosKey((int)(2 * pos.y), (int)(pos.x * 2));
                UpdateMapGrounds((int)(pos.x * 2), (int)(pos.y * 2), mapGrounds);

                _mapEditor.mapRooms[roomID].mapGroundPos[nowGround].position = pos;
                var ground = _mapEditor.mapRooms[roomID].mapGroundPos[nowGround];
                mapGroundPos[tempKey] = ground;
            }
        }
        _mapEditor.mapRooms[roomID].roomSize.minX += (int)(_mapEditor.mapRooms[roomID].offsetPos.x * 2);
        _mapEditor.mapRooms[roomID].roomSize.maxX += (int)(_mapEditor.mapRooms[roomID].offsetPos.x * 2);
        _mapEditor.mapRooms[roomID].roomSize.minY += (int)(_mapEditor.mapRooms[roomID].offsetPos.y * 2);
        _mapEditor.mapRooms[roomID].roomSize.maxY += (int)(_mapEditor.mapRooms[roomID].offsetPos.y * 2);
        _mapEditor.mapRooms[roomID].mapGrounds = new Dictionary<int, List<int>>(mapGrounds);
        _mapEditor.mapRooms[roomID].mapGroundPos.Clear();
        _mapEditor.mapRooms[roomID].mapGroundPos = new Dictionary<int, MapEditorBase.MapGround>(mapGroundPos);

    }
    /// <summary>
    /// 添加边缘墙壁
    /// </summary>
    /// <param name="YPos"></param>偏移后的Y最值
    /// <param name="XPos"></param>偏移后的X最值
    /// <param name="roomID"></param>
    private void AddEdgeWall(Tuple<int, int> YPos, Tuple<int, int> XPos,int roomID)
    {
        //下上左右方向
        Tuple<int, int>[] dic = { new Tuple<int, int>(-5, 0),new Tuple<int, int>(5, 0),  new Tuple<int, int>(0, -5), new Tuple<int, int>(0, 5) };
        Tuple<int, int>[] p = {new Tuple<int, int>(-1, 0), new Tuple<int, int>(1, 0),  new Tuple<int, int>(0, -1), new Tuple<int, int>(0, 1) };
        for (int y = YPos.Item1; y <= YPos.Item2; y += 5)
        {
            for (int x = XPos.Item1; x <= XPos.Item2; x += 5)
            {
                int nowGround = GetHashPosKey(y, x);
                var name = "Ground";
                //检查下上左右方向上是否有地砖
                for (int n = 0; n < 4; n++)
                {
                    if (_mapEditor.mapRooms[roomID].mapGroundPos.ContainsKey(nowGround))
                    {
                        var pos = _mapEditor.mapRooms[roomID].mapGroundPos[nowGround].position;
                        int key = GetHashPosKey(y + dic[n].Item1, x + dic[n].Item2);
                        if (!_mapEditor.mapRooms[roomID].mapGroundPos.ContainsKey(key))
                        {
                            //如果是门的位置
                            if (_mapEditor.mapRooms[roomID].mapDoors.doorDic.ContainsKey(nowGround) &&
                                (int)_mapEditor.mapRooms[roomID].mapDoors.doorDic[nowGround] == n)//_mapEditor.mapRooms[roomID].mapDoors.doorIContains(_mapEditor.mapRooms[roomID].mapGroundPos[nowGround].position)                          
                                continue;

                            MapEditorBase.MapWall wall = new MapEditorBase.MapWall();
                            wall.param = new List<int>();
                            wall.position = new Vector3(pos.x + p[n].Item2, pos.y + p[n].Item1, pos.z);
                            switch (n)
                            {
                                case 0:
                                case 1:
                                    wall.sceneType = SceneType.HorWall;
                                    break;
                                case 2:
                                case 3:
                                    wall.sceneType = SceneType.VerWall;
                                    break;
                            }
                            _mapEditor.mapRooms[roomID].mapWalls.Add(wall);
                        }
                    }
                }
                if (_mapEditor.mapRooms[roomID].mapGroundPos.ContainsKey(nowGround))
                {
                    var ground = _mapEditor.mapRooms[roomID].mapGroundPos[nowGround];
                    AddMonoList(null, ground, name);
                }
            }
        }
    }
    private void AddEdgeWall()
    {
        //下上左右方向
        Tuple<int, int>[] dic = { new Tuple<int, int>(-5, 0), new Tuple<int, int>(5, 0), new Tuple<int, int>(0, -5), new Tuple<int, int>(0, 5) };
        Tuple<int, int>[] p = { new Tuple<int, int>(-1, 0), new Tuple<int, int>(1, 0), new Tuple<int, int>(0, -1), new Tuple<int, int>(0, 1) };
        foreach (var item in _mapEditor.mapCorridors)
        {
            bool vertical = true;
            MapEditorBase.CorridorDirection direction = item.direction; //_mapEditor.mapRooms[roomID].mapDoors.doorDic[GetHashPosKey((int)(doorPos.y * 2), (int)(doorPos.x * 2))];
            switch (direction)
            {
                case MapEditorBase.CorridorDirection.Vertical:
                    vertical = true;
                    break;
                case MapEditorBase.CorridorDirection.Horizontal:
                    vertical = false;
                    break;
            }
            foreach (var grounds in item.mapGrounds)
            {
                foreach (var ground in grounds.Value)
                {
                    int nowGround = GetHashPosKey(grounds.Key, ground);
                    int y = grounds.Key;
                    int x = ground;
                    var name = "Ground";
                    var pos = item.mapGroundPos[nowGround].position;
                    //检查下上左右方向上是否有地砖
                    for (int i = 0; i < 4; i++)
                    {
                        int key = GetHashPosKey(y + dic[i].Item1, x + dic[i].Item2);
                        if (nowGround == item.doorKey.x)
                        {
                            if (vertical && i == (int)MapEditorBase.DoorDirection.Below)
                                continue;
                            if (!vertical && i == (int)MapEditorBase.DoorDirection.Left)
                                continue;
                        }
                        if (nowGround == item.doorKey.y)
                        {
                            if (vertical && i == (int)MapEditorBase.DoorDirection.Above)
                                continue;
                            if (!vertical && i == (int)MapEditorBase.DoorDirection.Right)
                                continue;
                        }
                        if (!item.mapGroundPos.ContainsKey(key))
                        {
                            MapEditorBase.MapWall wall = new MapEditorBase.MapWall();
                            wall.param = new List<int>();
                            wall.position = new Vector3(pos.x + p[i].Item2, pos.y + p[i].Item1, pos.z);
                            switch (i)
                            {
                                case 0:
                                case 1:
                                    wall.sceneType = SceneType.HorWall;
                                    break;
                                case 2:
                                case 3:
                                    wall.sceneType = SceneType.VerWall;
                                    break;
                            }
                            item.mapWalls.Add(wall);
                        }
                    }
                    if (item.mapGroundPos.ContainsKey(nowGround))
                    {
                        var g = item.mapGroundPos[nowGround];
                        AddMonoList(null, g, name);
                    }
                }
            }
        }
    }
    /// <summary>
    /// 更新mapGrounds
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="mapGrounds"></param>
    private void UpdateMapGrounds(int x,int y, Dictionary<int, List<int>> mapGrounds)
    {
        if (mapGrounds.ContainsKey(y))
        {
            mapGrounds[y].Add(x);
            //扫一遍
            int num = mapGrounds[y].Count - 1;
            for (int i = 0; i < num; i++)
            {
                if (mapGrounds[y][i] > mapGrounds[y][num])
                {
                    int t1 = mapGrounds[y][i];
                    int t2 = mapGrounds[y][num];
                    mapGrounds[y][i] = t2;
                    mapGrounds[y][num] = t1;
                }
            }
        }
        else
        {
            List<int> temp = new List<int>();
            temp.Add(x);
            mapGrounds.Add(y, temp);
        }
    }
    /// <summary>
    /// 初始化所有墙壁
    /// </summary>
    /// <param name="roomID"></param>
    private void InitWall(int roomID)
    {
        foreach (var item in _mapEditor.mapRooms[roomID].mapWalls)
        {
            var isBoss = Data.Instance.TableAgent.GetInt("AllRoom", _mapEditor.mapRooms[roomID].mapID.ToString(), "IsBoss");
            var pos = item.position;
            string name = "";
            if (item.sceneType == SceneType.HorWall)
                name = isBoss == 1 ? "HorBossWall" : "HorWall";
            if (item.sceneType == SceneType.VerWall)
                name = isBoss == 1 ? "VerBossWall" : "VerWall";
            if (item.sceneType == SceneType.HorWall)
                AddMonoList(item, null, name);
            if (item.sceneType == SceneType.VerWall)
                AddMonoList(item, null, name);
        }
    }
    private void InitWall()
    {
        if (_mapEditor.mapCorridors.Count == 0)
            return;
        foreach (var item in _mapEditor.mapCorridors)
        {
            foreach(var wall in item.mapWalls)
            {
                var pos = wall.position;
                string name = "";
                if (wall.sceneType == SceneType.HorWall)
                    name = "HorWall";
                if (wall.sceneType == SceneType.VerWall)
                    name = "VerWall";
                if (wall.sceneType == SceneType.HorWall)
                    AddMonoList(wall, null, name);
                if (wall.sceneType == SceneType.VerWall)
                    AddMonoList(wall, null, name);

            }
        }
    }
    /// <summary>
    /// 添加到MonoList
    /// </summary>
    /// <param name="mapWall"></param>
    /// <param name="mapGround"></param>
    /// <param name="name"></param>
    private void AddMonoList(MapEditorBase.MapWall mapWall = null, MapEditorBase.MapGround mapGround = null,string name = "")
    {
        SceneMonoData _sceneMono = new SceneMonoData();
        if (mapGround != null)
        {
        _sceneMono.position = mapGround.position;
        _sceneMono.sceneType = mapGround.sceneType;
        _sceneMono.attr = mapGround.attr;
        _sceneMono.Params = mapGround.param;
        }
        if(mapWall != null)
        {
            _sceneMono.position = mapWall.position;
            _sceneMono.sceneType = mapWall.sceneType;
            _sceneMono.attr = MonoAttribute.None;
            _sceneMono.Params = mapWall.param;
        }
        GameMgr.Get<ISceneMonoManager>().AddSceneMono(name, _sceneMono);
    }
    /// <summary>
    /// 加载地图文件
    /// </summary>
    /// <param name="MapName"></param>
    /// <returns></returns>
    private MapEditorBase.MapRoom GetRoomMap(int mapNum)
    {
        if (_mapFile.Count <= mapNum)
        {
            Debug.LogError("文件不存在" + mapNum);
        }
        MapEditorBase.MapRoom jsonText = new MapEditorBase.MapRoom();
        var save = _mapFile[mapNum];//File.ReadAllText(savePath);
        try
        {
            jsonText = JsonConvert.DeserializeObject<MapEditorBase.MapRoom>(save);
        }
        catch(Exception e)
        {
            Debug.Log(e);
        }
        return jsonText;
    }
    /// <summary>
    /// 得到最近的地砖
    /// </summary>
    /// <param name="target"></param>
    /// <returns></returns>
    public MapEditorBase.MapGround GetNearestGround(Vector3 target)
    {
        float tempX = (target.x + 1.25f) * 2;
        float tempY = (target.y + 1.25f) * 2;
        int x = ((int)(tempX / 5) + (tempX < 0 ? -1 : 0)) * 5;
        int y = ((int)(tempY / 5) + (tempY < 0 ? -1 : 0)) * 5;
        if (GetCertainGround(y, x) == null)
        {
            return null;
        }
        return GetCertainGround(y, x);
    }

    /// <summary>
    /// 得到某一块地砖
    /// </summary>
    /// <param name="y"></param>纵坐标*2取整
    /// <param name="x"></param>横坐标*2取整
    /// <returns></returns>
    public MapEditorBase.MapGround GetCertainGround(int y, int x)
    {
        int key = GetHashPosKey(y, x);
        int i = 0;
        for(i = 0;i < _mapEditor.roomLen * _mapEditor.roomWide;i++)
        {
            var item = _mapEditor.mapRooms[i].roomSize;
            if (y <= item.maxY && y >= item.minY && x <= item.maxX && x >= item.minX)
                if (_mapEditor.mapRooms[i].mapGroundPos.ContainsKey(key))
                {
                    return _mapEditor.mapRooms[i].mapGroundPos[key];
                }
        }
        foreach (var item in _mapEditor.mapCorridors)
        {
            if (item.mapGroundPos.ContainsKey(key))
            {
                return item.mapGroundPos[key];
            }
        }
        //Debug.LogError("Can't find the key:" + key);
        return null;
    }
    public MapEditorBase.MapGround GetCertainGround(Vector3 vec)
    {
        int x = (int)(vec.x * 2);
        int y = (int)(vec.y * 2);
        return GetCertainGround(y, x);
    }
    /// <summary>
    /// 用地砖坐标得到房间ID
    /// </summary>
    /// <param name="y"></param>纵坐标*2取整
    /// <param name="x"></param>横坐标*2取整
    /// <returns></returns>
    public int GetRoomID(int y, int x)
    {
        int key = GetHashPosKey(y, x);
        int i = 0;
        for (i = 0; i < _mapEditor.roomLen * _mapEditor.roomWide; i++)
        {
            var item = _mapEditor.mapRooms[i].roomSize;
            if (y <= item.maxY && y >= item.minY && x <= item.maxX && x >= item.minX)
                if (_mapEditor.mapRooms[i].mapGroundPos.ContainsKey(key))
                    return i;
        }
        return -1;
    }
    /// <summary>
    /// 用地砖坐标得到房间ID
    /// </summary>
    /// <param name="y"></param>纵坐标*2取整
    /// <param name="x"></param>横坐标*2取整
    /// <returns></returns>
    public int GetRoomID(MapEditorBase.MapGround ground)
    {
        int x = (int)(ground.position.x * 2);
        int y = (int)(ground.position.y * 2);
        int key = GetHashPosKey(y, x);
        int i = 0;
        for (i = 0; i < _mapEditor.roomLen * _mapEditor.roomWide; i++)
        {
            var item = _mapEditor.mapRooms[i].roomSize;
            if (y <= item.maxY && y >= item.minY && x <= item.maxX && x >= item.minX)
                if (_mapEditor.mapRooms[i].mapGroundPos.ContainsKey(key))
                    return i;
        }
        return -1;
    }
    /// <summary>
    /// 得到HashKey
    /// </summary>
    /// <param name="y"></param>纵坐标*2取整
    /// <param name="x"></param>横坐标*2取整
    /// <returns></returns>
    public int GetHashPosKey(int y, int x)
    {
        int pre = x << 16;
        return (pre | y);
    }
    public int GetHashPosKey(Vector3 pos)
    {
        int y = (int)(pos.y * 2);
        int x = (int)(pos.x * 2);
        int pre = x << 16;
        return (pre | y);
    }


    public bool CheckClear(bool AllClear)
    {
        bool IsCleared = true;
        foreach(GameObject obj in GameMgr.Get<IMonoManager>().GetAllMono()._ObjList.Values)
        {
            if (obj.tag.Contains("Enemy"))
            {
                IsCleared = false;
            }
        }
        foreach(SpawnObjData sb in GameMgr.Get<ISpawnManager>().GetSpawnObjDatas()._spawnData.Values)
        {
            if (!sb.NotActivated)
            {
                IsCleared = false;
            }
        }
        if (AllClear && GameMgr.Get<ISpawnManager>().GetSpawnObjDatas()._ObjList.Count > 0)
        {
            IsCleared = false;
        }
        return IsCleared;
    }
    public void ClearMap()
    {
        GameMgr.Get<IMonoManager>().ClearAll(MonoBase.MonoTag.All);
        GameMgr.Get<ISceneMonoManager>().ClearAll();
        GameMgr.Get<IBulletManager>().ClearAll();
        GameMgr.Get<ISpawnManager>().ClearAll();
    }

    private bool CheckCleared()
    {
        return (GameMgr.Get<IMonoManager>().GetAllMono()._ObjList.Count == 0)
            && (GameMgr.Get<ISceneMonoManager>().GetAllSceneMono()._ObjList.Count == 0)
            && (GameMgr.Get<IBulletManager>().GetAllBullet()._ObjList.Count == 0)
            && (GameMgr.Get<ISpawnManager>().GetSpawnObjDatas()._ObjList.Count == 0);
    }
    public void ToTheNextRoom(Action action)
    {
        GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentDifficulty += 
            Data.Instance.TableAgent.GetInt("AllMap", GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentRoomID.ToString(), "MapDifficultyPlus");//房间id的逻辑
        //切换房间回蓝回血
        for (int i = 0; i < GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas.Count; i++)
        {
            GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.HPData.HPValue =
                GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.HPData.HPCeiling;
            for (int j = 0; j < GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.SkillList.Count; j++)
            {
                GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.MPData.MPValue =
                    GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.MPData.MPCeiling;
            }
            GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.monoRealtimeStatus = new MonoRealtimeStatus();
        }
        CoroutineManager.Instance.StartCoroutine(NextRoom(action));
    }
    IEnumerator NextRoom(Action action)
    {
        ClearMap();
        while (!CheckCleared())//场上物体清理干净了再初始化下一张地图
        {
            yield return 0;
        }
        yield return new WaitForSeconds(0.3f);
        InitMapData(GetMapName(GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentDifficulty, out int CurrentRoomID));
        GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentRoomID = CurrentRoomID;
        action();
    }

    public string GetMapName(int CurDifficulty,out int CurrentRoomID)
    {
        //首张地图特殊处理
        if(GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentRoomID == 0)
        {
            GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.EnteredRoom.Add(0);
            GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.EnteredRoom.Add(1);
            CurrentRoomID = 1;
            return "Map1";
        }
        //Boss地图特殊处理
        if(CurDifficulty >= 500)
        {
            CurrentRoomID = 23;
            return "MapBoss1";
        }

        //获取所有地图
        int ID = 0;
        string MapName = "";
        Dictionary<int, int> MapTempDatas = new Dictionary<int, int>();
        List<string> IDs = Data.Instance.TableAgent.CollectKey1("AllMap");
        for(int i=0;i< IDs.Count; i++)
        {
            MapTempDatas.Add(int.Parse(IDs[i]), Data.Instance.TableAgent.GetInt("AllMap", IDs[i], "MapDifficulty"));
        }

        //获得难度最近的x张地图
        List<int> RandomIDs = new List<int>();
        for(int j = 0; j < 3; j++)
        {
            float DifficultyTemp = Mathf.Infinity;
            int closetID = 0;
            foreach (int id in MapTempDatas.Keys)
            {
                if (GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.EnteredRoom.Contains(id))
                {
                    continue;
                }
                if (RandomIDs.Contains(id))
                {
                    continue;
                }
                if (Mathf.Abs(GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentDifficulty - MapTempDatas[id]) < DifficultyTemp)
                {
                    DifficultyTemp = Mathf.Abs(GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.CurrentDifficulty - MapTempDatas[id]);
                    closetID = id;
                }
            }
            RandomIDs.Add(closetID);
        }
        //选择其中一张
        int Temp = 0;
        Temp = UnityEngine.Random.Range(0, RandomIDs.Count);
        ID = RandomIDs[Temp];

        CurrentRoomID = ID;
        GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[0].PlayerLevelData.EnteredRoom.Add(CurrentRoomID);
        MapName = Data.Instance.TableAgent.GetString("AllMap", CurrentRoomID.ToString(), "MapName");
        Debug.Log("CurrentMap:" + MapName);
        return MapName;
    }
}
